package com.digua.atools.tools;

import com.digua.atools.tools.listener.DataToAttrListener;
import com.digua.atools.tools.listener.DataToDataListener;
import com.digua.atools.tools.listener.FilterListener;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

/**
 * @author:digua
 * @dat:2021/8/21
 * @description:集合工具
 */
public class CollUtil {


    /**
     * 判断List是否是空
     *
     * @param list
     * @return
     */
    public static boolean isBlank(List list) {
        return list == null || list.size() == 0;
    }

    /**
     * 判断List是否不为空
     *
     * @param list
     * @return
     */
    public static boolean isNotBlank(List list) {
        return !isBlank(list);
    }

    /**
     * 获取元素所在集合的第一个位置
     *
     * @param list
     * @param item
     * @param <T>
     * @return
     */
    public static <T> int getIndex(List<T> list, T item) {
        if (isBlank(list)) {
            return -1;
        }
        return list.indexOf(item);
    }

    /**
     * 获取元素所在集合的第一个位置
     *
     * @param list
     * @param listener
     * @param <T>
     * @return
     */
    public static <T> int getIndex2(List<T> list, FilterListener<T> listener) {
        if (isBlank(list) || listener == null) {
            return -1;
        }
        T t = getVal(list, d -> listener.filter(d));
        return getIndex(list, t);
    }

    /**
     * 获取元素所在集合的最后一个位置
     *
     * @param list
     * @param item
     * @param <T>
     * @return
     */
    public static <T> int getLastIndex(List<T> list, T item) {
        if (isBlank(list)) {
            return -1;
        }
        return list.lastIndexOf(item);
    }

    /**
     * 将一种类型List转变成另一种类型的List
     *
     * @param list
     * @param listener
     * @param defList  默认值
     * @param <T1>
     * @param <T2>
     * @return
     */
    public static <T1, T2> List<T2> listToList(List<T1> list, DataToDataListener<T1, T2> listener, List<T2>... defList) {
        if (list == null || listener == null) {
            return defList == null || defList.length <= 0 ? null : defList[0];
        }
        if (isBlank(list)) {
            return new ArrayList<>();
        }
        List<T2> res = new ArrayList<>();
        for (T1 t1 : list) {
            res.add(listener.d2d(t1));
        }
        return res;
    }

    /**
     * 比较两个List元素是值是否一样
     *
     * @param list1
     * @param list2
     * @return
     */
    public static <T> boolean equals(List<T> list1, List<T> list2) {
        if (list1 == null && list2 == null) {
            return true;
        }
        if (list1 == null || list2 == null) {
            return false;
        }
        return list1.containsAll(list2) && list2.containsAll(list1);
    }

    /**
     * List过虑
     *
     * @param list     要进行过滤的List
     * @param listener 过虑监听
     * @return
     */
    public static <T> List<T> filter(List<T> list, FilterListener<T> listener) {
        if (isBlank(list)) {
            return list;
        }
        List<T> res = toList();
        for (T t : list) {
            if (listener.filter(t)) {
                res.add(t);
            }
        }
        return res;
    }

    /**
     * 获取集合中的指定位置的值
     *
     * @param list
     * @param index
     * @param <T>
     * @return
     */
    public static <T> T getVal(List<T> list, int index) {
        return getVal(list, index, null);
    }

    /**
     * 获取集合中的指定元素
     *
     * @param list
     * @param listener
     * @param <T>
     * @return
     */
    public static <T> T getVal(List<T> list, FilterListener<T> listener) {
        if (isBlank(list) || listener == null) {
            return null;
        }
        for (T t : list) {
            if (listener.filter(t)) {
                return t;
            }
        }
        return null;
    }

    /**
     * 获取集合中的指定位置的值
     *
     * @param list
     * @param index
     * @param def   默认值
     * @param <T>
     * @return
     */
    public static <T> T getVal(List<T> list, int index, T def) {
        return isBlank(list) || index < 0 || index > list.size() - 1 ? def : list.get(index);
    }

    /**
     * 去重
     *
     * @param list
     */
    public static <T> List<T> distinct(List<T> list) {
        if (isBlank(list) || list.size() == 1) {
            return list;
        }
        HashSet hs = new HashSet(list);
        return new ArrayList<>(hs);
    }

    /**
     * List中是否包含某个元素
     *
     * @param list
     * @param t
     * @param <T>
     * @return
     */
    public static <T> boolean contains(List<T> list, T t) {
        if (isBlank(list) || t == null) {
            return false;
        }
        return list.contains(t);
    }

    /**
     * List中是否包含其中的某个元素
     *
     * @param list
     * @param t
     * @param <T>
     * @return
     */
    public static <T> boolean hasContains(List<T> list, T... t) {
        if (isBlank(list) || t == null || t.length <= 0) {
            return false;
        }
        for (T t1 : t) {
            if (list.contains(t1)) {
                return true;
            }
        }
        return false;
    }

    /**
     * List中是否包含所有的元素
     *
     * @param list
     * @param t
     * @param <T>
     * @return
     */
    public static <T> boolean allContains(List<T> list, T... t) {
        if (isBlank(list) || t == null || t.length <= 0) {
            return false;
        }
        return list.containsAll(toList(t));
    }

    /**
     * 转成List
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T> List<T> toList(T... t) {
        ArrayList<T> res = new ArrayList<T>(t.length);
        Collections.addAll(res, t);
        return res;
    }

    /**
     * 转成LinkedList
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T> LinkedList<T> toLinkedList(T... t) {
        LinkedList<T> res = new LinkedList<>();
        Collections.addAll(res, t);
        return res;
    }

    /**
     * 获取List中的最大值
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T> T max(List<T> list) {
        return max(list, null);
    }

    /**
     * 获取List中的最大值
     *
     * @param list
     * @param listener
     * @param <T>
     * @param <A>
     * @return
     */
    public static <T, A> T max(List<T> list, DataToAttrListener<T, A> listener) {
        if (isBlank(list)) {
            return null;
        }
        if (list.size() == 1) {
            return list.get(0);
        }
        try {
            list = sort(list, listener);
            return list.get(list.size() - 1);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取List中的最小值
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T> T min(List<T> list) {
        return min(list, null);
    }

    /**
     * 获取List中的最小值
     *
     * @param list
     * @param listener
     * @param <T>
     * @param <A>
     * @return
     */
    public static <T, A> T min(List<T> list, DataToAttrListener<T, A> listener) {
        if (isBlank(list)) {
            return null;
        }
        if (list.size() == 1) {
            return list.get(0);
        }
        try {
            list = sort(list, listener);
            return list.get(0);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * List排序
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T> List<T> sort(List<T> list) {
        return sort(list, null);
    }

    /**
     * List排序
     *
     * @param list
     * @param listener
     * @param <T>
     * @param <A>
     * @return
     */
    public static <T, A> List<T> sort(List<T> list, DataToAttrListener<T, A> listener) {
        return sort(list, false, listener);
    }


    /**
     * List排序
     *
     * @param list
     * @param isDesc   是否倒序
     * @param listener
     * @param <T>
     * @param <A>
     * @return
     */
    public static <T, A> List<T> sort(List<T> list, boolean isDesc, DataToAttrListener<T, A> listener) {
        if (isBlank(list) || list.size() == 1) {
            return list;
        }
        if (listener != null) {
            A a = listener.toAttr(list.get(0));
            if (!ObjUtil.isBaseDataOrStr(a)) {
                new Exception("暂不支持非基本数据类型的数据").printStackTrace();
                return null;
            }
        }
        Collections.sort(list, (o1, o2) -> {
            int res = 0;
            if (listener != null) {
                A a1 = listener.toAttr(o1);
                A a2 = listener.toAttr(o2);
                res = ObjUtil.compare(a1, a2);
            } else {
                res = ObjUtil.compare(o1, o2);
            }
            return res * (isDesc ? -1 : 1);
        });
        return list;
    }

    /**
     * 获取集合数据数量
     *
     * @param list
     * @return
     */
    public static int size(List list) {
        return size(list, null);
    }

    /**
     * 获取集合数据数量
     *
     * @param list
     * @param listener
     * @param <T>
     * @return
     */
    public static <T> int size(List<T> list, FilterListener<T> listener) {
        if (isBlank(list)) {
            return 0;
        }
        if (listener == null) {
            return list.size();
        }
        int size = 0;
        for (T t : list) {
            if (listener.filter(t)) {
                ++size;
            }
        }
        return size;
    }
}
